import { AuthError, authenticateRequest } from "@/lib/auth/server";
import { GateFileError, getGateFileContent } from "@/lib/chat/gate-files";
import { getOwnedAttachment } from "@/lib/db/attachments";
import { getPool } from "@/lib/db/pool";
import { getAttachmentObject } from "@/lib/storage/s3";
export const runtime = "nodejs";
const noStoreHeaders = { "Cache-Control": "no-store" };
export async function GET(request: Request, { params }: { params: Promise<{ id: string }> }): Promise<Response> {
try {
const user = await authenticateRequest(request);
const authorization = request.headers.get("Authorization");
if (!authorization) throw new AuthError();
const attachment = await getOwnedAttachment(getPool(), user.id, (await params).id);
if (!attachment) {
return Response.json(
{ error: "Вложение не найдено" },
{ status: 404, headers: noStoreHeaders },
);
}
const content = attachment.gateFileId
? await getGateFileContent(attachment.gateFileId, authorization, request.signal)
: attachment.objectKey
? await getAttachmentObject(attachment.objectKey)
: null;
if (!content) throw new Error("Attachment has no storage reference");
return new Response(content, {
headers: {
...noStoreHeaders,
"Content-Disposition": `attachment; filename*=UTF-8''${encodeFilename(attachment.name)}`,
"Content-Length": String(attachment.size),
"Content-Type": attachment.contentType,
"X-Content-Type-Options": "nosniff",
},
});
} catch (error) {
return Response.json(
{
error:
error instanceof AuthError ||
(error instanceof GateFileError && error.reason === "unauthorized")
? "Unauthorized"
: "Хранилище вложений временно недоступно",
},
{
status:
error instanceof AuthError ||
(error instanceof GateFileError && error.reason === "unauthorized")
? 401
: 503,
headers: noStoreHeaders,
},
);
}
}
function encodeFilename(value: string): string {
return encodeURIComponent(value).replace(/[!'()*]/g, (character) =>
`%${character.charCodeAt(0).toString(16).toUpperCase()}`,
);
}